package com.pingan.generator.api.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.event.spi.SaveOrUpdateEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.pingan.generator.api.entity.ColInfo;
import com.pingan.generator.api.entity.mapper.ColInfoMapper;
import com.pingan.generator.api.service.GetService;
import com.pingan.generator.api.tool.CollectionTool;
import com.pingan.generator.api.util.Constains;

@SuppressWarnings({ "rawtypes", "unchecked" })
@Service("getService")
public class GetServiceImpl implements GetService {
	@Autowired
	private ColInfoMapper colInfoMapper;

	@Override
	public void saveList(String mapString, long interfaceId, long fatherId, boolean mark) {
		Map<String, Object> map = JSON.parseObject(mapString, Map.class);
		String reqOrResp = map.get("colReqOrResp") == null ? null : map.remove("colReqOrResp").toString();

		Map<String, Object> para = new HashMap<String, Object>();
		para.put("interfaceId", interfaceId);
		Set<String> newKey = map.keySet();

		for (String s : newKey) {
			Map<String, Object> map2 = null;
			List<Map> listMap = null;

			try {
				map2 = JSON.parseObject(map.get(s).toString());
			} catch (Exception e) {
				try {
					listMap = JSON.parseArray(map.get(s).toString(), Map.class);
				} catch (Exception e2) {
					return;
				}
			}

			if (listMap != null && listMap.size() != 0) {
				fatherId = saveColList(listMap, reqOrResp, fatherId, interfaceId, mark, s);
			} else {
				fatherId = saveColOrObject(map2, reqOrResp, interfaceId, fatherId, mark, s);
			}
		}
	}

	@Override
	public void updateList(String mapString, long interfaceId, long fatherId, boolean mark) {
		Map<String, Object> map = JSON.parseObject(mapString, Map.class);

		// 入参或出参类型获取
		String reqOrResp = map.get("colReqOrResp") == null ? null : map.remove("colReqOrResp").toString();

		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("interfaceId", interfaceId);
		paraMap.put("fatherId", fatherId);
		paraMap.put("reqOrResp", reqOrResp);

		// 数据库查询入参或者出参查询
		List<Map<String, Object>> dbList = colInfoMapper.getColDetailList(paraMap);
		Set<String> dbKey = new HashSet<String>();
		if (dbList != null && dbList.size() != 0) {
			for (Map<String, Object> keyMap : dbList) {
				dbKey.add(keyMap.get("col") == null ? null : keyMap.get("col").toString());
			}
		}

		// 最新字段key
		Set<String> newKey = map.keySet();

		// 新增和减少字段处理
		desOrAddCol(dbList, map, null, dbKey, newKey, interfaceId, fatherId, mark);
		for (String s : newKey) {	
			Map<String, Object> dataMap = null;
			List<Map> listMap = null;
			try {
				dataMap = JSON.parseObject(map.get(s).toString());
			} catch (Exception e) {
				try {
					listMap = JSON.parseArray(map.get(s).toString(), Map.class);
				} catch (Exception e2) {
					return;
				}
			}

			// 数据库字段包含最新字段(字段修改)
			if (dbKey.contains(s)) {
				// 修改成非Object类型
				if (isListOrObjectOr(dataMap, listMap).equals(Constains.colAttr.COL_PT)) {
					ColInfo newCl = JSON.parseObject(map.get(s).toString(), ColInfo.class);
					for (Map<String, Object> keyMap : dbList) {
						if (s.equals(keyMap.get("col"))) {
							ColInfo dbCl = JSON.parseObject(JSON.toJSONString(keyMap), ColInfo.class);
							dbCl.setId(null);
							dbCl.setReqOrResp(newCl.getReqOrResp());
							newCl.setAttr(getSimpleAttr(newCl.getAttr()));
							newCl.setInterfaceId(dbCl.getInterfaceId());
							System.out.println(JSON.toJSONString(dbCl) + "&&" + JSON.toJSONString(newCl));
							if (JSON.toJSONString(dbCl).equals(JSON.toJSONString(newCl))) {
								System.out.println("接口字段没有发生变化");
								break;
							} else {
								updateAndAdd(keyMap, newCl);
								break;
							}
						}
					}
					continue;
				} else if (isListOrObjectOr(dataMap, listMap).equals(Constains.colAttr.COL_Object)
						|| isListOrObjectOr(dataMap, listMap).equals(Constains.colAttr.COL_LIST)) {
					// List类型字段修改 或者修改成为Object类型
					fatherId = updateObjectOrList(dbList, listMap, dataMap, fatherId, s, reqOrResp, interfaceId, mark);
				}
			}
		}
	}

	/**
	 * 类型变化比较 然后保存数据
	 * 
	 * @param dbList
	 * @param listMap
	 * @param dataMap
	 * @param fatherId
	 * @param key
	 * @param reqOrResp
	 * @param interfaceId
	 * @param mark
	 * @return
	 */
	private long updateObjectOrList(List<Map<String, Object>> dbList, List<Map> listMap, Map<String, Object> dataMap,
			long fatherId, String key, String reqOrResp, long interfaceId, boolean mark) {

		// Object类型字段修改 或者修改成为Object类型
		if (dataMap != null) {
			dataMap.remove("colReqOrResp");
		}

		Set<String> dbKeySun = new HashSet<>();
		Set<String> newKeySun = new HashSet<>();

		for (Map<String, Object> dbMap : dbList) {
			if (key.equals(dbMap.get("col"))) {
				fatherId = dbMap.get("id") == null ? 0 : Integer.valueOf(dbMap.get("id").toString());
				if ((!"Y".equals(dbMap.get("isList")) && listMap != null)
						|| (!"Y".equals(dbMap.get("isObject")) && dataMap != null)) {
					// 修改该节点下面所有字段状态为移除状态，并保存新字段
					fatherId = updateAttr(listMap, dataMap, dbMap, reqOrResp, interfaceId, fatherId, mark, key);

				} else {
					List<ColInfo> dbInfoList = colInfoMapper.getColInfoListByFatherId(dbMap);
					if (dataMap != null && dataMap.size() != 0) {
						// Object/List类型比较
						for (ColInfo dbInfo : dbInfoList) {
							long id = dbInfo.getId();
							String attr = dbInfo.getAttr();
							ColInfo newInfo = new ColInfo();
							dbKeySun.add(dbInfo.getCol());
							if (dataMap.keySet().contains(dbInfo.getCol())) {
								String newJonsString = dataMap.get(dbInfo.getCol()).toString();
								if (compareChange(dbInfo, newInfo, newJonsString)) {
									System.out.println("接口没有发生变化");
								} else {
									newInfo = JSON.parseObject(newJonsString, ColInfo.class);

									Map<String, Object> para = new HashMap<>();
									para.put("id", id);
									para.put("attr", attr);
									updateAndAdd(para, newInfo);

									// 如果修改成为Object类型或者List泛型
									if (newInfo.getCol() == null && newInfo.getReqOrResp() == null) {
										updateList(newJonsString, interfaceId, newInfo.getId(), mark);
									}
								}
							}
						}
					} else {
						// Object/List类型比较
						newKeySun = listMap.get(0).keySet();
						for (ColInfo dbInfo : dbInfoList) {
							long id = dbInfo.getId();
							String attr = dbInfo.getAttr();
							ColInfo newInfo = new ColInfo();
							dbKeySun.add(dbInfo.getCol());
							for(String string:newKeySun){
								if (dbInfo.getCol().equals(string)) {
									String newJonsString = listMap.get(0).get(string).toString();
									if (compareChange(dbInfo, newInfo, newJonsString)) {
										System.out.println("接口没有发生变化");
									} else {
										newInfo = JSON.parseObject(newJonsString, ColInfo.class);
										Map<String, Object> para = new HashMap<>();
										para.put("id", id);
										para.put("attr", attr);
										updateAndAdd(para, newInfo);

										// 如果修改成为Object类型或者List泛型
										if (newInfo.getCol() == null && newInfo.getReqOrResp() == null) {
											updateList(newJonsString, interfaceId, newInfo.getId(), mark);
										}
									}
								}
								
							}
	
							}
					}
				}

				// 新增和减少字段处理
				if (dataMap != null) {
					desOrAddCol(dbList, dataMap, null, dbKeySun, dataMap.keySet(), interfaceId, fatherId, mark);
					fatherId = 0;
					break;
				} else {
					desOrAddCol(dbList, null, listMap, dbKeySun, newKeySun, interfaceId, fatherId, mark);
					fatherId = 0;
				}

			}
		}
		return fatherId;
	}

	/**
	 * compare DTO if equals return true else return false
	 * 
	 * @param dbInfo
	 * @param newInfo
	 * @param dataMap
	 * @return
	 */
	private boolean compareChange(ColInfo dbInfo, ColInfo newInfo, String newJonsString) {
		String dbJonsString = JSON.toJSONString(dbInfo);
		System.out.println("dbJonsString1 : " + dbJonsString + " ^^ newJonsString1 : " + newJonsString);
		newInfo = JSON.parseObject(newJonsString, ColInfo.class);
		newInfo.setAttr(getSimpleAttr(newInfo.getAttr()));
		newInfo.setColFatherId(dbInfo.getColFatherId());
		newInfo.setInterfaceId(dbInfo.getInterfaceId());
		newInfo.setColSunId(dbInfo.getColSunId());
		dbInfo.setReqOrResp(newInfo.getReqOrResp());
		dbInfo.setColSunId(null);
		dbInfo.setColFatherId(null);
		dbInfo.setId(null);
		dbInfo.setInterfaceId(null);
		dbJonsString = JSON.toJSONString(dbInfo);
		newJonsString = JSON.toJSONString(newInfo);
		System.out.println("dbJonsString2 : " + dbJonsString + " ^^  newJonsString2 : " + newJonsString);
		if (dbJonsString.equals(newJonsString)) {
			return true;
		}
		return false;
	}

	// 普通类型,泛型转换Object类型
	private long updateAttr(List<Map> listMap, Map<String, Object> dataMap, Map<String, Object> dbMap, String reqOrResp,
			long interfaceId, long fatherId, boolean mark, String s) {

		// 类型变化修改之前得字段为移除状态
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("id", dbMap.get("id"));
		colInfoMapper.updateStatus(paraMap);

		// 如果List修改成为Object
		paraMap.put("fatherId", dbMap.get("id"));

		if (Constains.colAttr.COL_LIST.equals(dbMap.get("attr"))) {

			// 移除父节点下面得所有字段
			colInfoMapper.updateStatusByFatherId(paraMap);

			// 保存新得Object类型
			return saveColOrObject(dataMap, reqOrResp, interfaceId, fatherId, mark, s);
		} else if (Constains.colAttr.COL_Object.equals(dbMap.get("attr"))) {
			// 移除父节点下面得所有字段
			colInfoMapper.updateStatusByFatherId(paraMap);

			// 保存新得Object类型
			return saveColList(listMap, reqOrResp, fatherId, interfaceId, mark, s);
		}
		return fatherId;
	}

	/**
	 * 新增或减少字段
	 * 
	 * @param map
	 * @param dbKey
	 * @param newKey
	 * @param interfaceId
	 * @param fatherId
	 * @param mark
	 * @return
	 */
	private void desOrAddCol(List<Map<String, Object>> dbList, Map<String, Object> dataMap, List<Map> listMap,
			Set<String> dbKey, Set<String> newKey, long interfaceId, long fatherId, boolean mark) {
		// 数据库减少的字段
		List<String> desKey = CollectionTool.getNotContain(new ArrayList<String>(dbKey), new ArrayList<String>(newKey));
		System.out.println("减少的键值为 : " + desKey);
		for (String string : desKey) {
			for (Map<String, Object> keyMap : dbList) {
				if (string.equals(keyMap.get("col"))) {
					updateAndAdd(keyMap, null);
				}
			}
		}

		// 有新增key值
		List<String> addKey = CollectionTool.getNotContain(new ArrayList<String>(newKey), new ArrayList<String>(dbKey));
		System.out.println("新增的键值为 : " + addKey);
		if (addKey != null && addKey.size() != 0) {
			if (dataMap != null && dataMap.size() != 0) {
				for (String string : addKey) {
					Map<String, Object> addMap = new HashMap<String, Object>();
					addMap.put(string, dataMap.get(string));
					saveList(JSON.toJSONString(addMap), interfaceId, fatherId, mark);
				}
			} else if (listMap != null && listMap.size() != 0) {
				for (String string : addKey) {
					for (Map<String, Object> map : listMap) {
						Map<String, Object> addMap = new HashMap<String, Object>();
						if (string.equals(map.get("col"))) {
							addMap.put(string, map);
							saveList(JSON.toJSONString(addMap), interfaceId, fatherId, mark);
						}
					}
				}
			}
		}
	}

	/**
	 * Object或者List
	 * 
	 * @param dataMap
	 * @param listMap
	 * @return
	 */
	private String isListOrObjectOr(Map<String, Object> dataMap, List<Map> listMap) {
		if (dataMap != null && dataMap.get("col") == null && dataMap.get("reqOrResp") == null) {
			return Constains.colAttr.COL_Object;
		} else if (listMap != null && listMap.size() != 0) {
			return Constains.colAttr.COL_LIST;
		}
		return Constains.colAttr.COL_PT;
	}

	/**
	 * 修改成非Object,List类型时 需移除父节点下所有字段
	 * 
	 * @param paraMap
	 * @param keyMap
	 * @param newCl
	 */
	private void updateAndAdd(Map<String, Object> keyMap, ColInfo newCl) {
		// 修改旧字段的字段状态为移除状态
		keyMap.put("type", Constains.colType.REMOVE_COL);
		colInfoMapper.updateStatusById(keyMap);

		// 如果是Object类型或者是List类型则修改下面所有字字段为移除状态
		if ("Y".equals(keyMap.get("isList")) || "Y".equals(keyMap.get("isObject"))) {
			keyMap.put("fatherId", keyMap.get("id"));
			colInfoMapper.updateStatusByFatherId(keyMap);
		}
		if (newCl != null) {
			// 新增字段
			newCl.setType(Constains.colType.ADD_COL);
			colInfoMapper.saveObject(newCl);

			if (newCl.getCol() == null && newCl.getAttr() == null) {
			}
		}

	}

	/**
	 * 获取类型简称
	 * 
	 * @param attr
	 * @return
	 */
	private String getSimpleAttr(Object attr) {
		String arrt1 = attr == null ? "" : attr.toString();
		if (arrt1.contains(".")) {
			return arrt1.substring(arrt1.lastIndexOf(".") + 1);
		}
		return arrt1;
	}

	/**
	 * 数据处理
	 * 
	 * @param info
	 * @param map
	 */
	private void handleData(ColInfo info, Map<String, Object> map) {
		info.setReqOrResp(map.get("reqOrResp") == null ? null : map.get("reqOrResp").toString());
		info.setCol(map.get("col") == null ? null : map.get("col").toString());
		info.setColName(map.get("colName") == null ? null : map.get("colName").toString());
		info.setIsNull(map.get("isNull") == null ? "N" : map.get("isNull").toString());
		info.setIsObject(map.get("isObject") == null ? "N" : map.get("isObject").toString());
		info.setIsList(map.get("isList") == null ? "N" : map.get("isList").toString());
		info.setAttr(getSimpleAttr(map.get("attr")));
	}

	/**
	 * Object类型，基本类型数据保存
	 * 
	 * @param colInfo
	 * @param dataMap
	 * @param reqOrResp
	 * @param interfaceId
	 * @param fatherId
	 * @param mark
	 * @param key
	 */
	private long saveColOrObject(Map<String, Object> dataMap, String reqOrResp, long interfaceId, long fatherId,
			boolean mark, String key) {
		ColInfo colInfo = new ColInfo();
		// 如果是Object类型
		if (dataMap != null && dataMap.get("col") == null && dataMap.get("reqOrResp") == null) {
			colInfo = new ColInfo();
			fatherId = saveListOrObjectFather(Constains.colAttr.COL_Object, fatherId, key, reqOrResp, interfaceId);
			saveList(dataMap.toString(), interfaceId, fatherId, mark);
			return 0;
		} else {
			// 基本类型(非Object类型)
			colInfo.setInterfaceId(interfaceId);
			colInfo.setIsObject("N");
			colInfo.setIsNull(dataMap.get("isNull") == null ? "N" : dataMap.get("isNull").toString());
			colInfo.setIsList(dataMap.get("isList") == null ? "N" : "Y");
			colInfo.setColFatherId(fatherId);
			colInfo.setType(Constains.colType.ADD_COL);
			handleData(colInfo, dataMap);
			colInfoMapper.save(colInfo);
			return fatherId;
		}
	}

	/**
	 * List及泛型数据保存
	 * 
	 * @param colInfo
	 * @param listMap
	 * @param fatherId
	 * @param interfaceId
	 * @param mark
	 * @param key
	 * @return
	 */
	private long saveColList(List<Map> listMap, String reqOrResp, long fatherId, long interfaceId, boolean mark,
			String key) {
		// 保存List(泛型)----->FATHER节点
		fatherId = saveListOrObjectFather(Constains.colAttr.COL_LIST, fatherId, key, reqOrResp, interfaceId);

		// List(泛型)下面所有子节点
		Set<String> set2 = listMap.get(0).keySet();
		for (String s2 : set2) {
			String ls = listMap.get(0).get(s2).toString();
			if (s2.equals("list")) {
				saveColList((List<Map>) JSON.parseObject(ls, Map.class), reqOrResp, fatherId, interfaceId, mark, s2);
				fatherId = 0;
			} else {
				if ("1".equals(ls) || "2".equals("ls")) {
					continue;
				}
				Map<String, Object> map3 = JSON.parseObject(ls, Map.class);
				fatherId = saveColOrObject(map3, reqOrResp, interfaceId, fatherId, mark, key);
			}
		}
		return fatherId = 0;
	}

	/**
	 * 保存父节点Col 返回fatherId
	 * 
	 * @param colType
	 * @param fatherId
	 * @param key
	 * @param reqOrResp
	 * @param interfaceId
	 * @return
	 */
	private long saveListOrObjectFather(String colType, long fatherId, String key, String reqOrResp, long interfaceId) {
		ColInfo colInfo = new ColInfo();
		colInfo.setCol(key);
		colInfo.setReqOrResp(reqOrResp);
		colInfo.setInterfaceId(interfaceId);
		colInfo.setAttr(colType);
		colInfo.setColFatherId(fatherId);
		colInfo.setIsObject(colType.equals("Object") ? "Y" : "N");
		colInfo.setIsList(colType.equals("List") ? "Y" : "N");
		colInfo.setIsNull("Y");
		colInfo.setType(Constains.colType.ADD_COL);
		colInfoMapper.saveObject(colInfo);
		return colInfo.getId();
	}

}
